package com.my.menu.modelcombination.popup.actions;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.text.html.HTMLDocument.HTMLReader.IsindexAction;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.emf.common.command.BasicCommandStack;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CommandStack;
import org.eclipse.emf.common.command.CommandStackListener;
import org.eclipse.emf.common.ui.dialogs.ResourceDialog;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.domain.IEditingDomainProvider;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory;
import org.eclipse.emf.edit.ui.action.ControlAction;
import org.eclipse.emf.edit.ui.action.LoadResourceAction;
import org.eclipse.emf.edit.ui.util.EditUIUtil;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;

import com.my.mytask.mytask.impl.ContConImpl;

import org.eclipse.bpmn2.ExtensionAttributeValue;
import org.eclipse.bpmn2.impl.ProcessImpl;
import org.js.model.rbac.impl.AccessControlModelImpl;


public class LoadModel_anotherVersion implements IObjectActionDelegate {

	private Shell shell;
	private IFile ifile;
	private ISelection iselection;
	private ComposedAdapterFactory adapterFactory;
	private URI resourceURI;
	private AdapterFactoryEditingDomain editingDomain;
	private Resource origRes;
	private Resource goalRes;
	private final int OK = 0;
	private final int CANCEL = 1;

	/**
	 * Constructor for Action1.
	 */
	public LoadModel_anotherVersion() {
		super();
	}

	/**
	 * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
	 */
	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
		System.out.println("setActivePart");
		iselection = targetPart.getSite().getSelectionProvider().getSelection();

		if (iselection instanceof IStructuredSelection) {
			Object obj = ((IStructuredSelection)iselection).getFirstElement();
			ifile = (IFile) Platform.getAdapterManager().getAdapter(obj,
					IFile.class);
			if (ifile == null) {
				if (obj instanceof IAdaptable) {
					ifile = (IFile) ((IAdaptable) obj).getAdapter(IFile.class);
				}
			}
			if (ifile != null) {
				resourceURI = URI.createPlatformResourceURI(ifile.getFullPath()
						.toString(), true);
				initializeEditingDomain();
				createModel();
			}
		}
		shell = targetPart.getSite().getShell();
	}
	
	/**
	 * This sets up the editing domain for the model editor.
	 */
	protected void initializeEditingDomain() {
		// Create an adapter factory that yields item providers.
		adapterFactory = new ComposedAdapterFactory(
				ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
		adapterFactory
				.addAdapterFactory(new ResourceItemProviderAdapterFactory());
		// TODO: check if we need the bpmn item
		// adapterFactory.addAdapterFactory(new
		// RoleItemProviderAdapterFactory());
		adapterFactory
				.addAdapterFactory(new ReflectiveItemProviderAdapterFactory());
		// Create the command stack that will notify this editor as commands are
		// executed.
		BasicCommandStack commandStack = new BasicCommandStack();
		// Create the editing domain with a special command stack.
		//
		editingDomain = new AdapterFactoryEditingDomain(adapterFactory,
				commandStack, new HashMap<Resource, Boolean>());
	}
	
	// TODO: add delete model method

	/**
	 * @see IActionDelegate#run(IAction)
	 */
	public void run(IAction action) {
		System.out.println("run");

		ResourceDialog rd = new ResourceDialog(shell, "Load Model", SWT.OPEN);
		int state = rd.open();
		ResourceSet resourceSet = editingDomain.getResourceSet();

		if (state != CANCEL) {
			if (rd.getURIText() != "") {
				editingDomain.loadResource(rd.getURIText());
				goalRes = resourceSet.getResource(rd.getURIs().get(0), false);
				System.out.println(rd.getURIs().get(0).toString());
				loadACModel();
			}
		}
//		System.out.println(editingDomain.getResourceSet().getResources());
	}

	/**
	 * @see IActionDelegate#selectionChanged(IAction, ISelection)
	 */
	public void selectionChanged(IAction action, ISelection selection) {
		System.out.println("selectionChanged");
	}


	/**
	 * This returns the editing domain.
	 */
	public EditingDomain getEditingDomain() {
		return editingDomain;
	}

	/**
	 * This is the method called to load a resource into the editing domain's
	 * resource set.
	 */
	public void createModel() {
		Exception exception = null;
		origRes = null;
		try {
			// Load the resource
			//
			origRes = editingDomain.getResourceSet().getResource(resourceURI,
					true);
		} catch (Exception e) {
			exception = e;
			origRes = editingDomain.getResourceSet().getResource(resourceURI,
					false);
		}
		System.out.println("before loading: "
				+ editingDomain.getResourceSet().getResources());
	}

	/**
	 * connect role model to bpmn model
	 */
	public void loadACModel() {
		// EList<EObject> origContents =origRes.getContents();
		TreeIterator<EObject> origIt = origRes.getAllContents();
		// EList<EObject> goalContents = goalRes.getContents();
		TreeIterator<EObject> goalIt = goalRes.getAllContents();

		AccessControlModelImpl goalEle = null;
		ProcessImpl origEle = null;

		while (goalIt.hasNext()) {
			EObject object = goalIt.next();
			if (object instanceof AccessControlModelImpl) {
				goalEle = (AccessControlModelImpl) object;
			}
		}
		System.out.println("goalEle.toString(): " + goalEle.toString());

		while (origIt.hasNext()) {
			EObject object = origIt.next();
			if (object instanceof ProcessImpl) {
				if (goalEle != null) {
					origEle = (ProcessImpl) object;
				}
			}
		}
		System.out.println("origEle.toString(): " + origEle.toString());
		System.out.println("((ProcessImpl)origEle).getExtensionValues(): "
				+ ((ProcessImpl) origEle).getExtensionValues().get(0).getValue().get(0));
		List<ExtensionAttributeValue> list= ((ProcessImpl) origEle).getExtensionValues();
		System.out.println("list: " + list);
		for(ExtensionAttributeValue eav:list){
			System.out.println("eav: " + eav);
		}
		ExtensionAttributeValue eav=((ProcessImpl) origEle).getExtensionValues().get(0);
		TreeIterator ti =eav.eAllContents();
		if(ti.hasNext()){
			Object object = ti.next();
			if(object.getClass().equals(ContConImpl.class)){
				((ContConImpl)object).setAcm(goalEle);
			}
			System.out.println("object: " + object.getClass());
		}
//		ContConImpl object =(ContConImpl) (((ProcessImpl) origEle).getExtensionValues().get(0).getValue().get(0));
	
		// ((ProcessImpl)origEle).getExtensionValues().get(0).eContents().add(goalEle);

		// Role role = RoleFactory.eINSTANCE.createRole();
		// while (it.hasNext()) {
		// EObject object = it.next();
		// if (object instanceof ContainerImpl) {
		// // ((LibraryImpl) object).getTasks().get(0).getRole().get;
		// }
		// System.out.println(object.getClass());
		// }
		 final Map<Object, Object> saveOptions = new HashMap<Object,
		 Object>();
		 saveOptions.put(Resource.OPTION_SAVE_ONLY_IF_CHANGED,
		 Resource.OPTION_SAVE_ONLY_IF_CHANGED_MEMORY_BUFFER);
		
		 try {
		 origRes.save(saveOptions);
		 } catch (IOException e) {
		 // TODO Auto-generated catch block
		 e.printStackTrace();
		 }

	}

}
